/*
 * http://www.digione.cn
 */
package com.jqd.framework.core.persistence.jpa2;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import javax.persistence.Query;
import javax.persistence.TypedQuery;

import org.springframework.util.Assert;

import com.jqd.framework.core.exception.DAOException;
import com.jqd.framework.core.persistence.BaseRepository;

/**
 * JAP 2.x DAO 层基本接口实现
 * 
 * @author liaozc@digione.cn
 * @date 2013-4-15
 * @since 1.0
 */
public abstract class Jpa2BaseRepositorySupport implements BaseRepository {
	
	private EntityManagerProvider entityManagerProvider;
	
	
	@Override
	public void saveEntity(Object entity) throws DAOException {
		Assert.notNull(entity, "Jpa2BaseRepositorySupport#saveEntity: entity can not be null");
		
		try {
			entityManagerProvider.getEntityManager().persist(entity);
		}
		catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	
	@Override
	public void deleteEntity(Object entity) throws DAOException {
		Assert.notNull(entity, "Jpa2BaseRepositorySupport#deleteEntity: entity can not be null");
		
		try {
			entityManagerProvider.getEntityManager().remove(entity);
		}
		catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	
	@Override
	public <T> void deleteEntity(Class<T> entityClazz, Serializable... primaryKeys)
			throws DAOException {
		Assert.notNull(entityClazz,
				"Jpa2BaseRepositorySupport#deleteEntity: entityClazz can not be null");
		Assert.notEmpty(primaryKeys,
				"Jpa2BaseRepositorySupport#deleteEntity: primaryKeys can not be empty");
		
		try {
			for (Serializable primaryKey : primaryKeys) {
				T t = entityManagerProvider.getEntityManager()
						.getReference(entityClazz, primaryKey);
				entityManagerProvider.getEntityManager().remove(t);
			}
		}
		catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	
	@Override
	public void updateEntity(Object entity) throws DAOException {
		Assert.notNull(entity, "Jpa2BaseRepositorySupport#updateEntity: entity can not be null");
		
		try {
			entityManagerProvider.getEntityManager().merge(entity);
		}
		catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	
	@Override
	public <T> T findEntity(Class<T> entityClazz, Serializable primaryKey) throws DAOException {
		Assert.notNull(primaryKey,
				"Jpa2BaseRepositorySupport#findEntity: primaryKey can not be null");
		
		try {
			return entityManagerProvider.getEntityManager().find(entityClazz, primaryKey);
		}
		catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	
	@Override
	public <T> T loadEntity(Class<T> entityClazz, Serializable primaryKey) throws DAOException {
		Assert.notNull(primaryKey,
				"Jpa2BaseRepositorySupport#loadEntity: primaryKey can not be null");
		
		try {
			return entityManagerProvider.getEntityManager().getReference(entityClazz, primaryKey);
		}
		catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	
	// protected method -------------
	
	protected <T> List<T> listByJpql(String jpql, Map<String, Object> filter, Class<T> entityClass) {
		Assert.hasText(jpql);
		
		TypedQuery<T> query = entityManagerProvider.getEntityManager().createQuery(jpql,
				entityClass);
		setQueryParameter(query, filter);
		return query.getResultList();
	}
	
	
	private void setQueryParameter(Query query, Map<String, Object> filter) {
		for (Map.Entry<String, Object> entry : filter.entrySet()) {
			query.setParameter(entry.getKey(), entry.getValue());
		}
	}
	
	
	// getter and setter ----------------
	public void setEntityManagerProvider(EntityManagerProvider entityManagerProvider) {
		this.entityManagerProvider = entityManagerProvider;
	}
	
}
